<?php

/*
	This file is part of Rectemplater
	Rec.php - The Loader class parses a recfile into an array.

	Copyright (C) 2022  Free Software Foundation, Inc

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

// https://www.gnu.org/software/recutils/manual/The-Rec-Format.html#The-Rec-Format

namespace Rec;


class Line {
	//enum Type {case SCHEMA; case FIELD; case COMMENT; case GAP;}
	const SCHEMA  = 0;
	const FIELD   = 1;
	const COMMENT = 2;
	const GAP     = 3;

	public string $key = "";
	public string $data = "";
	public int $type = 3;
}


class Loader {

	private array $source;
	private array $entries;
	private array $types;


	public function __construct($filename) {
		$source = file_get_contents($filename);
		$this->source = explode("\n", $source);
		$this->loadSchema();

		$this->entries = [];
		while ($entry = $this->nextEntry())
			array_push($this->entries, $entry);
	}

	public function getEntries() {
		return $this->entries;
	}


	private function next(): Line {
		$line = new Line();

		do {
			$load = array_shift($this->source);
			if (empty($load)) {
				return $line;
			} elseif ($load[0] === "+") {
				$line->data .= substr($load, 1);
			} else {
				$pos = strpos($load, ":");
				$line->key = substr($load, 0, $pos);
				$line->data = substr($load, $pos+2);
			}
		} while ($this->source[0] and $this->source[0][0] === "+");


		switch ($line->key[0]) {
			case "%":
				$line->type = Line::SCHEMA; break;
			case "#":
				$line->type = Line::COMMENT; break;
			default:
				$line->type = Line::FIELD; break;
		}

		/*$line->Type = match ($line->key[0]) {
			"%"     => Line::SCHEMA,
			"#"     => Line::COMMENT,
			default => Line::FIELD
		}*/

		return $line;
	}

	private function nextEntry() {
		$entry = [];
		while ( ($line=$this->next())->type !== Line::GAP )
			if ($line->type === Line::FIELD)
				$entry[$line->key] = $this->loadType($line->key, $line->data);
		// TODO: Check if its valid with schema
		return $entry;
	}

	private function loadSchema() {
		// TODO
		while ( ($line=$this->next())->type === Line::SCHEMA ) {
			switch ($line->key) {
				case "%type":
					$data = explode(" ", $line->data);
					$this->types[array_shift($data)] = implode(" ", $data);
					break;
			}
		}
	}

	private function loadType($key, $data) {
		if (!isset($this->types[$key]))
			return $data;

		$type = explode(" ", $this->types[$key]);
		switch($type[0]) {
			case "bool": return filter_var($data, FILTER_VALIDATE_BOOLEAN);
			default:     return $data;
		}
	}

}
